package network

import (
	"bytes"
	"context"
	"io"

	"gitee.com/simonxie979/skymeta/logutil"
)

const (
	CloseFrom_Self           = "close from self"           // 本端主动关闭
	CloseFrom_Remote         = "close from remote"         // 对端正常关闭
	CloseFrom_RemoteForcibly = "forcibly closed by remote" // 对端强制关闭
)

// 通信对象所属宿主
type ICommHost[T any] interface {
	OnConnect(sessionID uint64, addr string)        // 新连接处理函数
	OnDisconnect(sessionID uint64, err error)       // 连接断开处理函数
	OnMessage(sessionID uint64, msg T)              // 新消息处理函数
	Pack(payload T, buf *bytes.Buffer)              // 消息编码函数 编码后的数据直接写入连接
	Unpack(reader io.Reader) (payload T, err error) // 消息解码函数 从连接中解码数据
}

// NewCommunicator Make a communicator
func NewCommunicator[T any](ctx context.Context, host ICommHost[T], logger *logutil.Logger) *Communicator[T] {
	comm := new(Communicator[T])
	comm.ctx, comm.cancel = context.WithCancel(ctx)
	comm.host = host
	comm.sessionMng = newSessionMng(comm)
	comm.log = logger

	return comm
}
